package com.ada.base.security;

import com.ada.base.properties.SecurityProperties;
import com.ada.base.security.service.AuthorityService;
import com.ada.base.security.entity.Authority;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.*;

@Configuration
@EnableConfigurationProperties(SecurityProperties.class)
public class UrlMetadataSource implements FilterInvocationSecurityMetadataSource {

    private static final String[] AUTH_WHITELIST = {
            // -- swagger ui
            "/v2/api-docs",
            "/swagger-resources",
            "/swagger-resources/**",
            "/configuration/ui",
            "/configuration/security",
            "/swagger-ui.html",
            "/webjars/**",
            "/createSession",
            "/css/**",
            "js/**",
            "/ws2.html",
            "/img/**",
            "/fonts**"
    };

    private AuthorityService authorityService;
    private List<String> permitUrls = new ArrayList<>();
    private PathMatcher pathMatcher;

    public UrlMetadataSource(AuthorityService authorityService, SecurityProperties securityProperties) {
        this.authorityService = authorityService;
        String[] permitUrls = securityProperties.getPermitUrls();
        if (permitUrls == null)
            permitUrls = new String[]{};
        Collections.addAll(this.permitUrls, permitUrls);
        Collections.addAll(this.permitUrls, AUTH_WHITELIST);
        this.pathMatcher = new AntPathMatcher();
    }

    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) {
        FilterInvocation invocation = (FilterInvocation) object;

        String method = invocation.getRequest().getMethod();
        String requestUrl = invocation.getRequest().getRequestURI();

        if (permitUrls.stream().anyMatch(s -> pathMatcher.match(s, requestUrl)))
            return SecurityConfig.createList("ROLE_NONE");

        Authority authority = authorityService.findByUrlAndMethod(requestUrl, method);
        if (null != authority)
            return SecurityConfig.createList(authority.getCode());

        return SecurityConfig.createList("ROLE_LOGIN");
    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
